import { _decorator, instantiate, Prefab, Node, Vec2, randomRangeInt, tween, AudioClip, v3 } from 'cc';
import { SSS_Consts } from "../../../Script/Data/SSS_Consts";
import { bdlMgr } from "../../../Script/Manager/BundleManager_S";
import SSS_TimerManager from "../../../Script/Manager/SSS_TimerManager";
import S2048_Block from "./S2048_Block";
import { S2048_GameData } from "./S2048_GameData";
import S2048_GameManager from "./S2048_GameManager";
import { S2048_GameStorage } from "./S2048_GameStorage";
import S2048_Grid from "./S2048_Grid";
import { SSS_AudioManager } from 'db://assets/Script/Manager/SSS_AudioManager';

const { ccclass, property } = _decorator;

@ccclass('S2048CardFunctions')
export default class S2048_CardFunctions {
        //    /** 保存数据 */
        static SaveData() {
                let serialized = [];

                for (let index = 0; index < S2048_GameData.arrBlocks.length; index++) {
                        const block: S2048_Block = S2048_GameData.arrBlocks[index];
                        let item = block.toJSON();
                        serialized.push(item);
                }

                console.log(serialized);
                S2048_GameStorage.data[S2048_GameData.Game_mode].map = serialized;
                S2048_GameStorage.saveData();
        }
        //    /** 创建格子 */
        static async CreateGrid(_col: number, _row: number, _id) {
                const prefab = await bdlMgr.getRes<Prefab>(`S2048_Prefab`, `Grid`, Prefab);
                const node: Node = instantiate(prefab);
                const scrGrid: S2048_Grid = node.getComponent(S2048_Grid);
                scrGrid.init(_col, _row, _id);
                S2048_GameManager.Instance.Root_grid.addChild(node);
                return scrGrid;
        }
        //    /** 创建牌组 */
        static async CreateBlock(_col: number, _row: number, _point: number) {
                const prefab = await bdlMgr.getRes<Prefab>(`S2048_Prefab`, `Block`, Prefab);
                const node: Node = instantiate(prefab);
                const block: S2048_Block = node.getComponent(S2048_Block);
                S2048_GameManager.Instance.Root_block.addChild(node);
                block.init(_col, _row, _point);
                return block;
        }
        static async 随机空地生成一个方块(_id: number) {
                let arr = S2048_CardFunctions.获取所有空地();
                // console.log(`arr`, arr);
                let r = randomRangeInt(0, arr.length);
                let grid = arr[r];
                // console.log(`grid`, grid);

                const scrBlock: S2048_Block = await S2048_CardFunctions.CreateBlock(grid.col, grid.row, _id);
                S2048_GameData.arrBlocks.push(scrBlock);

                return scrBlock;
        }
        static async 指定地生成一个方块(_col: number, _row: number, _id: number) {
                const scrBlock: S2048_Block = await S2048_CardFunctions.CreateBlock(_col, _row, _id);
                S2048_GameData.arrBlocks.push(scrBlock);
        }
        static GetGrid(_col: number, _row: number) {
                // return S2048_GameData.arrBlocks.flat()
                //     .find(element => element.col === _col && element.row === _row);

                return S2048_GameData.arrGrids.find(e => e.col == _col && e.row == _row);

                // if (S2048_GameData.arrGrids[x] && S2048_GameData.arrGrids[x][y]) {
                //     return S2048_GameData.arrGrids[x][y];
                // }

                return null;
        }
        static GetBlock(_col: number, _row: number) {
                return S2048_GameData.arrBlocks.find(e => e.col == _col && e.row == _row);
        }
        static 当前格子是否是空地(_col, _row) {
                let block = S2048_CardFunctions.GetBlock(_col, _row);
                if (block) {
                        return false;
                }
                else {
                        return true;
                }
        }
        static 获取所有空地() {
                let arr = [];
                for (let _col = 1; _col <= S2048_GameData.col; _col++) {
                        for (let _row = 1; _row <= S2048_GameData.row; _row++) {
                                const is_empty = S2048_CardFunctions.当前格子是否是空地(_col, _row);
                                if (is_empty) {
                                        let grid: S2048_Grid = S2048_CardFunctions.GetGrid(_col, _row);
                                        arr.push(grid);
                                }
                        }
                }

                return arr;
        }
        static 获取所有非空地() {
                let arr = [];
                for (let x = 0; x < S2048_GameData.col; x++) {
                        for (let y = 0; y < S2048_GameData.row; y++) {
                                const is_empty = S2048_CardFunctions.当前格子是否是空地(x, y);
                                if (!is_empty) {
                                        let grid: S2048_Grid = S2048_CardFunctions.GetGrid(x, y);
                                        arr.push(grid);
                                }
                        }
                }

                return arr;
        }
        //    // 操作滑动
        public static OperateSlide(_direction: Vec2) {
                // console.log(`_direction`, _direction);

                // // 正在滑动中
                // if (S2048_GameData.isSlide == true) {
                //     return;
                // }

                // // 不在Play状态
               

                // // 昼夜切换弹框弹出
                // if (GameManager.Instance.dayNightState == DayNightState.Day2Night || GameManager.Instance.dayNightState == DayNightState.Night2Day) {
                //     SpecialEventPanel.Instance.On_Button_main();
                //     return;
                // }

                S2048_CardFunctions.StartMoveCells(_direction);
        }
        //    //开始移动格子
        public static StartMoveCells(_direction: Vec2) {
                // TipPanel.Instance.Show('滑动开始~~~');
                S2048_GameData.isSlide = true;
                S2048_GameData.direction = _direction;

                S2048_CardFunctions.MoveCells(_direction);

                // AudioManager.Instance.woosh.play();
                // AudioManager.Instance.woosh.volume = 0.2;
        }
        //    //移动格子
        public static MoveCells(_direction: Vec2) {
                // let startIndex: number = 0;
                // let endIndex: number = 0;
                // let add: number = 1;
                if (_direction.x == 0 && _direction.y == 1) {
                        //     startIndex = MapManager.Instance.row_start + MapManager.Instance.row - 1;
                        //     endIndex = MapManager.Instance.row_start;
                        //     add = -1;
                        S2048_CardFunctions.move_up();
                }
                else if (_direction.x == 0 && _direction.y == -1) {
                        S2048_CardFunctions.move_down();

                        //     startIndex = MapManager.Instance.row_start;
                        //     endIndex = MapManager.Instance.row_start + MapManager.Instance.row - 1;
                        //     add = +1;
                }
                if (_direction.x == -1 && _direction.y == 0) {
                        //     startIndex = MapManager.Instance.row_start + MapManager.Instance.row - 1;
                        //     endIndex = MapManager.Instance.row_start;
                        //     add = -1;
                        S2048_CardFunctions.move_left();

                }
                else if (_direction.x == 1 && _direction.y == 0) {

                        S2048_CardFunctions.move_right();

                        //     startIndex = MapManager.Instance.row_start;
                        //     endIndex = MapManager.Instance.row_start + MapManager.Instance.row - 1;
                        //     add = +1;
                }
        }
        // static moveAndMerge(row: number[]): { newRow: number[], scoreIncrease: number } {
        //     // 1. 移除所有0，让数字靠拢
        //     let newRow = this.removeZeros(row);
        //     let scoreIncrease = 0;
        //     // 2. 合并相邻的相同数字
        //     for (let i = 0; i < newRow.length - 1; i++) {
        //         if (newRow[i] === newRow[i + 1]) {
        //             newRow[i] *= 2;      // 合并
        //             newRow[i + 1] = 0;   // 被合并的位置置0
        //             scoreIncrease += newRow[i]; // 增加分数
        //         }
        //     }
        //     // 3. 再次移除合并产生的0
        //     newRow = this.removeZeros(newRow);
        //     // 4. 补0到原始长度
        //     while (newRow.length < S2048_GameData.col) {
        //         newRow.push(0);
        //     }
        //     return { newRow, scoreIncrease };
        // }
        // static removeZeros(row: number[]): number[] {
        //     return row.filter(num => num !== 0);
        // }
        static async move_up() {
                // console.log(`move_up`);

                let hasChanged = false;
                for (let index = 1; index <= S2048_GameData.col; index++) {
                        const columnChanged = await S2048_CardFunctions.上划一列(index);
                        hasChanged = hasChanged || columnChanged; // 只要有一列变化，就标记为 true
                }
                if (hasChanged) {
                        S2048_CardFunctions.滑动以后();
                        // this.生成新方块(); // 如果有变化，生成新方块
                }
                // else {
                //     this.CheckEnd(); // 如果无变化，检查是否无法移动
                // }
        }
        //    // 下落没问题
        static async move_down() {
                // console.log(`move_down`);

                let hasChanged = false;
                for (let index = 1; index <= S2048_GameData.col; index++) {
                        const columnChanged = await S2048_CardFunctions.下划一列(index);
                        hasChanged = hasChanged || columnChanged; // 只要有一列变化，就标记为 true
                }
                if (hasChanged) {
                        S2048_CardFunctions.滑动以后();
                        // this.生成新方块(); // 如果有变化，生成新方块
                }
                // else {
                //     this.CheckEnd(); // 如果无变化，检查是否无法移动
                // }
        }
        static async move_left() {
                // console.log(`move_left`);

                let hasChanged = false;
                for (let index = 1; index <= S2048_GameData.row; index++) {
                        const columnChanged = await S2048_CardFunctions.左划一行(index);
                        hasChanged = hasChanged || columnChanged; // 只要有一列变化，就标记为 true
                }
                if (hasChanged) {
                        S2048_CardFunctions.滑动以后();
                        // this.生成新方块(); // 如果有变化，生成新方块
                }
                // else {
                //     this.CheckEnd(); // 如果无变化，检查是否无法移动
                // }
        }
        static async move_right() {
                // console.log(`move_right`);

                let hasChanged = false;
                for (let index = 1; index <= S2048_GameData.row; index++) {
                        const columnChanged = await S2048_CardFunctions.右划一行(index);
                        hasChanged = hasChanged || columnChanged; // 只要有一列变化，就标记为 true
                }
                if (hasChanged) {
                        S2048_CardFunctions.滑动以后();
                        // this.生成新方块(); // 如果有变化，生成新方块
                }
                // else {
                //     this.CheckEnd(); // 如果无变化，检查是否无法移动
                // }
        }
        static CheckEnd() {
                let 是否结束 = S2048_CardFunctions.检查游戏是否结束();
                if (是否结束) {
                        S2048_GameManager.Instance.Lose();
                }
        }
        static 检查游戏是否结束() {
                for (let col = 1; col <= S2048_GameData.col; col++) {
                        for (let row = 1; row <= S2048_GameData.row; row++) {
                                const currentBlock = S2048_CardFunctions.GetBlock(col, row);

                                // 1. 检查当前是否为空
                                if (!currentBlock || currentBlock.removed) {
                                        return false; // 有空位，游戏继续
                                }

                                // 2. 检查右侧和下侧是否可以合并（避免重复检查左和上）
                                if (col < S2048_GameData.col) {
                                        const rightBlock = S2048_CardFunctions.GetBlock(col + 1, row);
                                        if (rightBlock && rightBlock.id === currentBlock.id) {
                                                return false; // 可右合并
                                        }
                                }

                                if (row < S2048_GameData.row) {
                                        const bottomBlock = S2048_CardFunctions.GetBlock(col, row + 1);
                                        if (bottomBlock && bottomBlock.id === currentBlock.id) {
                                                return false; // 可下合并
                                        }
                                }
                        }
                }

                // 所有格子满且无法合并，游戏结束
                return true;
        }
        static async 滑动以后() {
                await new Promise(res => SSS_TimerManager.Instance.scheduleOnce(res, S2048_GameData.move_duration + 0.01));
                S2048_CardFunctions.合并();

                await new Promise(res => SSS_TimerManager.Instance.scheduleOnce(res, 0.01));
                S2048_CardFunctions.恢复所有block状态();

                let block = await S2048_CardFunctions.随机空地生成一个方块(2);
                // console.log(`block`, block);
                block.node.scale = v3(0, 0, 0);

                S2048_CardFunctions.SaveData();

                if (!S2048_GameData.本次滑动是否有合并) {
                        let root = `audio/掉落音效`;
                        // let root = `audio/水音效1`;
                        bdlMgr.getRes<AudioClip>(SSS_Consts.BundleName.AUDIO, root, AudioClip).then(res => {
                                SSS_AudioManager.Instance.playSFX(res, false);
                        });
                }

                tween(block.node)
                        .to(0.14, { scale: v3(1, 1, 1,) })
                        .start();

                await new Promise(res => SSS_TimerManager.Instance.scheduleOnce(res, 0.2));
                this.CheckEnd(); // 如果无变化，检查是否无法移动
        }
        static async 左划一行(_row) {
                let hasChanged = false; // 默认无变化

                // 从左向右检测 (col=1是最左)
                for (let currentCol = 1; currentCol <= S2048_GameData.col; currentCol++) {
                        const currentBlock = S2048_CardFunctions.GetBlock(currentCol, _row);
                        if (!currentBlock || currentBlock.removed) continue;

                        let targetCol = currentCol;
                        let mergeTarget = null;

                        // 向左探测（向更小的列号移动）
                        while (targetCol > 1) {
                                const testCol = targetCol - 1;
                                const targetBlock = S2048_CardFunctions.GetBlock(testCol, _row);

                                if (!targetBlock) {
                                        // 空位，继续左移
                                        targetCol = testCol;
                                }
                                else if (!targetBlock.removed && targetBlock.id === currentBlock.id && !targetBlock.merged) {
                                        // 找到可合并目标
                                        mergeTarget = targetBlock;
                                        targetCol = testCol;
                                        break;
                                } else {
                                        // 遇到障碍物（不同数字或已合并的方块）
                                        break;
                                }
                        }

                        // 执行操作
                        if (mergeTarget) {
                                hasChanged = true;

                                // 合并操作
                                mergeTarget.id *= 2;
                                mergeTarget.merged = true;

                                S2048_GameData.Add_score(mergeTarget.id);

                                currentBlock.id *= 2;
                                currentBlock.removed = true;
                                currentBlock.col = targetCol;
                        }
                        else if (targetCol !== currentCol) {
                                hasChanged = true;

                                // 纯移动（没有合并，只是移动到空位）
                                currentBlock.col = targetCol;
                        }

                        currentBlock.MovePosition(S2048_GameData.move_duration);
                }

                return hasChanged; // 返回是否变化
        }
        static async 右划一行(_row) {
                let hasChanged = false; // 默认无变化

                // 从右向左检测 (col=1是最左)
                for (let currentCol = S2048_GameData.col; currentCol >= 1; currentCol--) {
                        const currentBlock = S2048_CardFunctions.GetBlock(currentCol, _row);
                        if (!currentBlock || currentBlock.removed) continue;

                        let targetCol = currentCol;
                        let mergeTarget = null;

                        // 向右探测（向更大的列号移动）
                        while (targetCol < S2048_GameData.col) {
                                const testCol = targetCol + 1;
                                const targetBlock = S2048_CardFunctions.GetBlock(testCol, _row);

                                if (!targetBlock) {
                                        // 空位，继续右移
                                        targetCol = testCol;
                                }
                                else if (!targetBlock.removed && targetBlock.id === currentBlock.id && !targetBlock.merged) {
                                        // 找到可合并目标
                                        mergeTarget = targetBlock;
                                        targetCol = testCol;
                                        break;
                                } else {
                                        // 遇到障碍物（不同数字或已合并的方块）
                                        break;
                                }
                        }

                        // 执行操作
                        if (mergeTarget) {
                                hasChanged = true;

                                // 合并操作
                                mergeTarget.id *= 2;
                                mergeTarget.merged = true;

                                S2048_GameData.Add_score(mergeTarget.id);

                                currentBlock.id *= 2;
                                currentBlock.removed = true;
                                currentBlock.col = targetCol;
                        }
                        else if (targetCol !== currentCol) {
                                hasChanged = true;

                                // 纯移动（没有合并，只是移动到空位）
                                currentBlock.col = targetCol;
                        }

                        currentBlock.MovePosition(S2048_GameData.move_duration);
                }

                return hasChanged; // 返回是否变化
        }
        static async 上划一列(_col) {
                let hasChanged = false; // 默认无变化

                // 从顶向下检测 (row=1是底部，所以顶部是S2048_GameData.row)
                for (let currentRow = S2048_GameData.row; currentRow >= 1; currentRow--) {
                        const currentBlock = S2048_CardFunctions.GetBlock(_col, currentRow);
                        if (!currentBlock || currentBlock.removed) continue;

                        let targetRow = currentRow;
                        let mergeTarget = null;

                        // 向上探测
                        while (targetRow < S2048_GameData.row) {
                                const testRow = targetRow + 1;
                                const targetBlock = S2048_CardFunctions.GetBlock(_col, testRow);

                                if (!targetBlock) {
                                        // 空位，继续上移
                                        targetRow = testRow;
                                }
                                else if (!targetBlock.removed && targetBlock.id === currentBlock.id && !targetBlock.merged) {
                                        // 找到可合并目标
                                        mergeTarget = targetBlock;
                                        targetRow = testRow;
                                        break;
                                } else {
                                        // 遇到障碍物
                                        break;
                                }
                        }

                        // 执行操作
                        if (mergeTarget) {
                                hasChanged = true;

                                // 合并操作
                                mergeTarget.id *= 2;
                                mergeTarget.merged = true;

                                S2048_GameData.Add_score(mergeTarget.id);

                                currentBlock.id *= 2;
                                currentBlock.removed = true;
                                currentBlock.row = targetRow;
                        }
                        else if (targetRow !== currentRow) {
                                hasChanged = true;

                                // 纯移动
                                currentBlock.row = targetRow;
                        }

                        currentBlock.MovePosition(S2048_GameData.move_duration);
                }

                return hasChanged; // 返回是否变化
        }
        static 下划一列(_col) {
                let hasChanged = false; // 默认无变化

                // 从底向上检测 (row=1是底部)
                for (let currentRow = 1; currentRow <= S2048_GameData.row; currentRow++) {
                        const currentBlock = S2048_CardFunctions.GetBlock(_col, currentRow);
                        if (!currentBlock || currentBlock.removed) continue;

                        let targetRow = currentRow;
                        let mergeTarget = null;

                        // 向下探测
                        while (targetRow > 1) {
                                const testRow = targetRow - 1;
                                const targetBlock = S2048_CardFunctions.GetBlock(_col, testRow);

                                if (!targetBlock) {
                                        // 空位，继续下落
                                        targetRow = testRow;
                                }
                                else if (!targetBlock.removed && targetBlock.id === currentBlock.id && !targetBlock.merged) {
                                        // 找到可合并目标
                                        mergeTarget = targetBlock;
                                        targetRow = testRow;
                                        break;
                                } else {
                                        // 遇到障碍物
                                        break;
                                }
                        }

                        // 执行操作
                        if (mergeTarget) {
                                hasChanged = true;

                                // 合并操作
                                mergeTarget.id *= 2;      // 数值合并
                                mergeTarget.merged = true;

                                S2048_GameData.Add_score(mergeTarget.id);

                                currentBlock.id *= 2;
                                currentBlock.removed = true; // 标记移除
                                // 被合并的方块移动到目标位置（视觉上下落）
                                currentBlock.row = targetRow;
                        }
                        else if (targetRow !== currentRow) {
                                hasChanged = true;

                                // 纯下落
                                currentBlock.row = targetRow;
                        }

                        currentBlock.MovePosition(S2048_GameData.move_duration);
                }

                return hasChanged; // 返回是否变化
        }
        static 合并() {
                let array = S2048_CardFunctions.findDuplicateItems(S2048_GameData.arrBlocks);
                console.log(`arr`, array);

                for (let index = 0; index < array.length; index++) {
                        const array_2 = array[index];

                        let block1 = array_2[0];
                        let block2 = array_2[1];

                        block1.Refresh();
                        tween(block1.node)
                                .to(0.14, { scale: v3(1.1, 1.1, 1.1) })
                                .call(() => {
                                })
                                .to(0.14, { scale: v3(1, 1, 1) })
                                .start();

                        let index_find = S2048_GameData.arrBlocks.indexOf(block2);
                        if (index_find != -1) {
                                S2048_GameData.arrBlocks.splice(index_find, 1);
                        }
                        block2.node.destroy();
                }

                S2048_GameData.本次滑动是否有合并 = array.length > 0;

                if (array.length > 0) {
                        // let root = `audio/收缩音效`;
                        // let root = `audio/水音效2`;
                        let root = `audio/水音效1`;

                        bdlMgr.getRes<AudioClip>(SSS_Consts.BundleName.AUDIO, root, AudioClip).then(res => {
                                SSS_AudioManager.Instance.playSFX(res, false);
                        });
                }
        }
        static 恢复所有block状态() {
                let array = S2048_CardFunctions.findDuplicateItems(S2048_GameData.arrBlocks);
                // console.log(`arr`, array);

                for (let index = 0; index < S2048_GameData.arrBlocks.length; index++) {
                        const block = S2048_GameData.arrBlocks[index];
                        // block.isComplete = false;
                        block.merged = false;
                        block.removed = false;
                }
        }
        static findDuplicateItems(arr) {
                const map = new Map<string, any[]>();

                for (const item of arr) {
                        const key = `${item.row}_${item.col}`; // 创建复合键
                        if (!map.has(key)) {
                                map.set(key, []);
                        }
                        map.get(key)!.push(item);
                }

                // 只返回有重复的组
                return Array.from(map.values()).filter(group => group.length > 1);
        }
        static GetRowCard(_row: number) {
                const cards = S2048_GameData.arrBlocks.filter(item => item.row == _row);
                // console.log(`cards`, cards);
                return cards;
        }
        static GetColCard(_col: number) {
                const cards = S2048_GameData.arrBlocks.filter(item => item.col == _col);
                // console.log(`cards`, cards);
                return cards;
        }
}